//
// VFS.cpp
// Usage: FileSystem resource
// CreateDate: 2009-05-18
// Author: MaJiuyue
//
#include "VFS.h"
#include "../schedule/Process.h"

VFS::VFS()
{
	/* Create sys filesystem */
	m_RootFS = new RootFS();
	m_UDevFS = new UDevFS();

//	m_UDevFS->CreateDevice("ad0s", 1, 1, 4);
	if(m_UDevFS->GetRoot()->Mount((Directory*)m_RootFS->GetRoot()->GetEntry(1)) != 0)
		panic("Mount UDevFS failed!");
		
	
	/* Create FileSystem resource */
	Resource * res = new Resource(this);
	ResourceManager.CreateResource(
		res,
		ServiceCallInterface::FileSystem::ResourceName
	);
	// Register interface
	res->RegisterInterface(
		(Resource::CallInterface0)&VFS::GetRoot,
		ServiceCallInterface::FileSystem::SCIID_GetRoot
	);
	res->RegisterInterface(
		(Resource::CallInterface2)&VFS::AddFileSystem,
		ServiceCallInterface::FileSystem::SCIID_AddFileSystem
	);
	res->RegisterInterface(
		(Resource::CallInterface1)&VFS::GetFileSystem,
		ServiceCallInterface::FileSystem::SCIID_GetFileSystem
	);
	res->RegisterInterface(
		(Resource::CallInterface1)&VFS::GetFile,
		ServiceCallInterface::FileSystem::SCIID_GetFile
	);
}

VFS::~VFS()
{
	// Destory external fs
	for(int i=0; i<m_ExtFS.getLength(); i++)
		delete m_ExtFS.removeFirst();
		
	// Destory sys fs
	delete m_RootFS;
	delete m_UDevFS;
}

/* Get root of VFS */
Directory * VFS::GetRoot()
{
	return m_RootFS->GetRoot();
}

/* Get file by path */
File * VFS::GetFile(const char * FilePath)
{
	Directory * cur_dir = NULL;
	File * file = NULL;
	char * path = NULL;
	char * fname = NULL;

	// Copy FilePath to buffer
	path = new char[strlen(FilePath)+1];
	strcpy(path, FilePath);

	// Check where to start
	if(path[0] == '/')				// root
		cur_dir = m_RootFS->GetRoot();
	else						// working
		cur_dir = GetCurrentProcess()->GetFCB()->GetWorkingDirectory();

	fname = strtok(path, "/");
	while(fname)
	{
		int index;
		for(index=0; index<cur_dir->GetEntryCount(); index++)
		{
			file = cur_dir->GetEntry(index);

			if(strcmp(file->GetFileName(), fname)==0)
			{
				fname = strtok(NULL, "/");
				break;
			}
		}
		if(index==cur_dir->GetEntryCount())
			return NULL;

		if(fname && file->GetType()!=FT_DIRECTORY)
		{
			kprintf("Not a directory!");
			return NULL;
		}
		cur_dir = (Directory *)file;
	}

	return file;
}

/* Add filesystem and mount it at mountpoint, if NULL, do not mount */
void VFS::AddFileSystem(FileSystem * fs, char * mountpoint)
{
	panic("Add ExtFS not implement!");
	m_ExtFS.insertLast(fs);
	if(mountpoint!=NULL)
	{

	}	
}

FileSystem * VFS::GetFileSystem(FS_TYPE type)
{
	if(type == FS_ROOT)
		return m_RootFS;
	else if(type == FS_UDEV)
		return m_UDevFS;
	else
		panic("VFS::GetFileSystem() not implement!");
}

